﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;

namespace RestaurantBooker.Controls
{
    public sealed class TitleBar : Control
    {
        public TitleBar()
        {
            this.DefaultStyleKey = typeof(TitleBar);
            
            if (App.Current.IsRunningOutOfBrowser && App.Current.HasElevatedPermissions)
            {
                this.MouseLeftButtonDown += new MouseButtonEventHandler(TitleBar_MouseLeftButtonDown);
            }
        }

        ~TitleBar()
        {
            //this.MouseLeftButtonDown -= TitleBar_MouseLeftButtonDown;
        }

        void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            App.Current.MainWindow.DragMove();
        }

        #region [ Constants ]
        // Parts constants
        private const string TITLEBAR_elementSettingButton = "SettingsButton";
        private const string TITLEBAR_elementFullScreenButton = "FullScreenButton";
        private const string TITLEBAR_elementMinimizeButton = "MinimizeButton";
        private const string TITLEBAR_elementMaximizeButton = "MaximizeButton";
        private const string TITLEBAR_elementCloseButton = "CloseButton";
        #endregion

        #region [ Private Fields ]
        private ButtonBase _settingsButton;
        private ButtonBase _fsButton;
        private ButtonBase _minButton;
        private ButtonBase _maxButton;
        private ButtonBase _closeButton;
        #endregion

        #region [ Public Methods ]

        /// <summary>
        /// Applies the control's template, retrieves the elements
        /// within it, and sets up events.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            // unsubscribe event handlers for previous template parts
            if (this._settingsButton != null)
            {
                this._settingsButton.Click -= _settingsButton_Click;
            }

            if (this._fsButton != null)
            {
                this._fsButton.Click -= _fsButton_Click;
            }

            if (App.Current.IsRunningOutOfBrowser && App.Current.HasElevatedPermissions)
            {
                if (this._minButton != null)
                {
                    this._minButton.Click -= _minButton_Click;
                }

                if (this._maxButton != null)
                {
                    this._maxButton.Click -= _maxButton_Click;
                }

                if (this._closeButton != null)
                {
                    this._closeButton.Click -= _closeButton_Click;
                }
            }

            _settingsButton = GetTemplateChild(TITLEBAR_elementSettingButton) as ButtonBase;
            _minButton = GetTemplateChild(TITLEBAR_elementMinimizeButton) as ButtonBase;
            _maxButton = GetTemplateChild(TITLEBAR_elementMaximizeButton) as ButtonBase;
            _closeButton = GetTemplateChild(TITLEBAR_elementCloseButton) as ButtonBase;
            _fsButton = GetTemplateChild(TITLEBAR_elementFullScreenButton) as ButtonBase;

            _settingsButton.Click += new RoutedEventHandler(_settingsButton_Click);
            _fsButton.Click += new RoutedEventHandler(_fsButton_Click);

            if (App.Current.IsRunningOutOfBrowser && App.Current.HasElevatedPermissions)
            {
                _minButton.Click += new RoutedEventHandler(_minButton_Click);
                _maxButton.Click += new RoutedEventHandler(_maxButton_Click);
                _closeButton.Click += new RoutedEventHandler(_closeButton_Click);
            }
            else
            {
                this._closeButton.Visibility = System.Windows.Visibility.Collapsed;
                this._maxButton.Visibility = System.Windows.Visibility.Collapsed;
                this._minButton.Visibility = System.Windows.Visibility.Collapsed;
            }
        }
        #endregion

        #region [ Events processing ]
        void _closeButton_Click(object sender, RoutedEventArgs e)
        {
            App.Current.MainWindow.Close();
        }

        void _maxButton_Click(object sender, RoutedEventArgs e)
        {
            if (Application.Current.MainWindow.WindowState == WindowState.Normal)
                Application.Current.MainWindow.WindowState = WindowState.Maximized;
            else
                Application.Current.MainWindow.WindowState = WindowState.Normal;
        }

        void _minButton_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.MainWindow.WindowState = WindowState.Minimized;
        }

        void _fsButton_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Host.Content.IsFullScreen = !Application.Current.Host.Content.IsFullScreen;
        }

        void _settingsButton_Click(object sender, RoutedEventArgs e)
        {
            if (ViewSettingsCommand != null)
                ViewSettingsCommand.Execute(null);
        }
        #endregion

        #region [ ViewSettingsCommand ]
        /// <summary>
        /// Gets or sets the command associated with the menu item.
        /// </summary>
        public ICommand ViewSettingsCommand
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        /// <summary>
        /// Identifies the Command dependency property.
        /// </summary>
        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
            "ViewSettingsCommand",
            typeof(ICommand),
            typeof(TitleBar),
            new PropertyMetadata(null, OnCommandChanged));

        /// <summary>
        /// Handles changes to the Command DependencyProperty.
        /// </summary>
        /// <param name="o">DependencyObject that changed.</param>
        /// <param name="e">Event data for the DependencyPropertyChangedEvent.</param>
        private static void OnCommandChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ((TitleBar)o).OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue);
        }

        /// <summary>
        /// Handles changes to the Command property.
        /// </summary>
        /// <param name="oldValue">Old value.</param>
        /// <param name="newValue">New value.</param>
        private void OnCommandChanged(ICommand oldValue, ICommand newValue)
        {
            if (null != oldValue)
            {
                oldValue.CanExecuteChanged -= new EventHandler(HandleCanExecuteChanged);
            }
            if (null != newValue)
            {
                newValue.CanExecuteChanged += new EventHandler(HandleCanExecuteChanged);
            }
            UpdateIsEnabled();
        }

        /// <summary>
        /// Handles the CanExecuteChanged event of the Command property.
        /// </summary>
        /// <param name="sender">Source of the event.</param>
        /// <param name="e">Event arguments.</param>
        private void HandleCanExecuteChanged(object sender, EventArgs e)
        {
            UpdateIsEnabled();
        }

        /// <summary>
        /// Updates the IsEnabled property.
        /// </summary>
        /// <remarks>
        /// WPF overrides the local value of IsEnabled according to ICommand, so Silverlight does, too.
        /// </remarks>
        private void UpdateIsEnabled()
        {
            IsEnabled = (null == ViewSettingsCommand) || ViewSettingsCommand.CanExecute(null);
            //ChangeVisualState(true);
        }
        #endregion

        #region [ Dependency properties ]
        /// <summary>
        /// The <see cref="TitleAppName" /> dependency property's name.
        /// </summary>
        public const string TitleAppNamePropertyName = "TitleAppName";

        /// <summary>
        /// Gets or sets the value of the <see cref="TitleAppName" />
        /// property. This is a dependency property.
        /// </summary>
        public string TitleAppName
        {
            get
            {
                return (string)GetValue(TitleAppNameProperty);
            }
            set
            {
                SetValue(TitleAppNameProperty, value);
            }
        }

        /// <summary>
        /// Identifies the <see cref="TitleAppName" /> dependency property.
        /// </summary>
        public static readonly DependencyProperty TitleAppNameProperty = DependencyProperty.Register(
            TitleAppNamePropertyName,
            typeof(string),
            typeof(TitleBar),
            new PropertyMetadata(null));



        /// <summary>
        /// The <see cref="TitleAppVersion" /> dependency property's name.
        /// </summary>
        public const string TitleAppVersionPropertyName = "TitleAppVersion";

        /// <summary>
        /// Gets or sets the value of the <see cref="TitleAppVersion" />
        /// property. This is a dependency property.
        /// </summary>
        public string TitleAppVersion
        {
            get
            {
                return (string)GetValue(TitleAppVersionProperty);
            }
            set
            {
                SetValue(TitleAppVersionProperty, value);
            }
        }

        /// <summary>
        /// Identifies the <see cref="TitleAppVersion" /> dependency property.
        /// </summary>
        public static readonly DependencyProperty TitleAppVersionProperty = DependencyProperty.Register(
            TitleAppVersionPropertyName,
            typeof(string),
            typeof(TitleBar),
            new PropertyMetadata(null));


        /// <summary>
        /// The <see cref="TitleConnectionStatus" /> dependency property's name.
        /// </summary>
        public const string TitleConnectionStatusPropertyName = "TitleConnectionStatus";

        /// <summary>
        /// Gets or sets the value of the <see cref="TitleConnectionStatus" />
        /// property. This is a dependency property.
        /// </summary>
        public string TitleConnectionStatus
        {
            get
            {
                return (string)GetValue(TitleConnectionStatusProperty);
            }
            set
            {
                SetValue(TitleConnectionStatusProperty, value);
            }
        }

        /// <summary>
        /// Identifies the <see cref="TitleConnectionStatus" /> dependency property.
        /// </summary>
        public static readonly DependencyProperty TitleConnectionStatusProperty = DependencyProperty.Register(
            TitleConnectionStatusPropertyName,
            typeof(string),
            typeof(TitleBar),
            new PropertyMetadata(null));


        /// <summary>
        /// The <see cref="TitleESTTime" /> dependency property's name.
        /// </summary>
        public const string TitleESTTimePropertyName = "TitleESTTime";

        /// <summary>
        /// Gets or sets the value of the <see cref="TitleESTTime" />
        /// property. This is a dependency property.
        /// </summary>
        public string TitleESTTime
        {
            get
            {
                return (string)GetValue(TitleESTTimeProperty);
            }
            set
            {
                SetValue(TitleESTTimeProperty, value);
            }
        }

        /// <summary>
        /// Identifies the <see cref="TitleESTTime" /> dependency property.
        /// </summary>
        public static readonly DependencyProperty TitleESTTimeProperty = DependencyProperty.Register(
            TitleESTTimePropertyName,
            typeof(string),
            typeof(TitleBar),
            new PropertyMetadata(null));
        #endregion
    }
        
}
